package com.geniusk.mqtt.strategy.impl;

import com.geniusk.common.utils.DeviceUtil;
import com.geniusk.common.utils.SpringContextUtil;
import com.geniusk.mqtt.strategy.MessageStrategy;
import com.geniusk.system.model.pojo.Device;
import com.geniusk.system.service.DeviceService;
import io.netty.channel.Channel;
import io.netty.handler.codec.mqtt.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;

/**
 * Connect Ack
 */
@Slf4j
@Component
public class ConnectAckMessageStrategy implements MessageStrategy {

    private final DeviceService deviceService = (DeviceService) SpringContextUtil.getBean("deviceServiceImpl");

    @Override
    public void sendResponseMessage(Channel channel, MqttMessage mqttMessage) {
        //解析接收的消息
        MqttConnectMessage mqttConnectMessage = (MqttConnectMessage)mqttMessage;
        int keepAliveTimeSeconds = mqttConnectMessage.variableHeader().keepAliveTimeSeconds();
        try {
            //解析授权码
            String username = mqttConnectMessage.payload().userName();
            Long deviceId = Long.parseLong(username);
            byte[] passwordInBytes = mqttConnectMessage.payload().passwordInBytes();
            String password = new String(passwordInBytes, StandardCharsets.UTF_8);
            String clientId = mqttConnectMessage.payload().clientIdentifier();
//            log.info("username:{} password:{} clientId:{} keepAliveTimeSeconds:{}",username, password, clientId, keepAliveTimeSeconds);
            Device device = deviceService.selectDeviceById(deviceId);
            if(device.getDeviceId().toString().equals(DeviceUtil.decryptStr(password,device.getDeviceSecret()))){
                connectAck(channel, mqttConnectMessage, MqttConnectReturnCode.CONNECTION_ACCEPTED);
            }else {
                connectAck(channel, mqttConnectMessage, MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD);
            }
        } catch (NumberFormatException e){
            log.error("无效的MQTT用户名");
        } catch (Exception e){
            log.error("Error in class:{}, message:{}", getClass().getSimpleName(),e.getMessage());
            e.printStackTrace();
            connectAck(channel, mqttConnectMessage, MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD);
        }
    }

    /**
     * 构建返回报文，固定报头
     * @param channel 信道
     * @param mqttConnectMessage 连接信息
     * @param mqttConnectReturnCode 连接确认状态
     */
    private void connectAck(Channel channel, MqttConnectMessage mqttConnectMessage, MqttConnectReturnCode mqttConnectReturnCode){
        MqttConnectVariableHeader mqttConnectVariableHeader = mqttConnectMessage.variableHeader();
        MqttFixedHeader mqttFixedHeader = mqttConnectMessage.fixedHeader();
        //构建返回报文，固定报头
        MqttConnAckVariableHeader mqttConnAckVariableHeader =new MqttConnAckVariableHeader(mqttConnectReturnCode, mqttConnectVariableHeader.isCleanSession());
        MqttFixedHeader mqttFixedHeaderBack = new MqttFixedHeader(MqttMessageType.CONNACK,mqttFixedHeader.isDup(), MqttQoS.AT_MOST_ONCE, mqttFixedHeader.isRetain(), 0x02);
        //	构建connAck消息体
        MqttConnAckMessage connAck = new MqttConnAckMessage(mqttFixedHeaderBack, mqttConnAckVariableHeader);
        channel.writeAndFlush(connAck);
    }
}
